﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.Security.Permissions;
using System.Security;
using System.Drawing.Text;
using System.Windows.Forms.VisualStyles;
using System.Drawing.Imaging;
using ICeFramework.Utilities.Drawing;

namespace ICeFramework.Win.UI
{
    public class TitlePanel : Panel
    {
        private int _titleHeight = 20;
        private Color _disabledColor = Color.Silver;
        private Button btnClose;

        public event EventHandler Close;

        private bool _hasCloseButton;
        public bool HasCloseButton
        {
            get { return _hasCloseButton; }
            set 
            {
                _hasCloseButton = value;
                btnClose.Visible = value;
            }
        }

        // Methods
        public TitlePanel()
        {
            base.SetStyle(ControlStyles.ContainerControl, true);
            base.SetStyle(ControlStyles.Selectable, false);
            this.TabStop = false;

            btnClose = new Button();
            btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            btnClose.Cursor = System.Windows.Forms.Cursors.Hand;
            btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            btnClose.FlatAppearance.BorderSize = 0;
            btnClose.FlatAppearance.MouseOverBackColor = Color.Transparent;
            btnClose.FlatAppearance.MouseDownBackColor = Color.Transparent;
            btnClose.Image = Properties.Resources.title_close;
            btnClose.Size = new System.Drawing.Size(18, 17);
            btnClose.UseVisualStyleBackColor = true;
            btnClose.Location = new System.Drawing.Point(this.Size.Width - btnClose.Size.Width - 10, 2);
            btnClose.TabStop = false;
            btnClose.BackColor = Color.Transparent;
            btnClose.Click += new EventHandler(btnClose_Click);
            btnClose.Visible = _hasCloseButton;
            this.Controls.Add(btnClose);
        }

        void btnClose_Click(object sender, EventArgs e)
        {
            OnClose();
        }

        public virtual void OnClose()
        {
            if (Close != null)
            {
                Close(this, EventArgs.Empty);
            }
        }

        protected override AccessibleObject CreateAccessibilityInstance()
        {
            return new TitlePanelAccessibleObject(this);
        }

        private void DrawTitleBox(PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            Rectangle clientRectangle = base.ClientRectangle;
            Pen pen = new Pen(ControlPaint.Light(_disabledColor, 1f));
            Pen pen2 = new Pen(ControlPaint.Dark(_disabledColor, 0f));
            try
            {
                ImageAttributes att = new ImageAttributes();
                att.SetWrapMode(WrapMode.Tile);
                graphics.DrawImage(Properties.Resources.title_left, new Point(0, 0));
                graphics.DrawImage(Properties.Resources.title_repeat, new Rectangle(7, 0, clientRectangle.Width - 14, 20),
                    0, 0, 1, 20, GraphicsUnit.Pixel, att);
                graphics.DrawImage(Properties.Resources.title_right, new Point(clientRectangle.Width - 7, 0));

                graphics.DrawLine(Pens.Black, new Point(0, 20), new Point(0, clientRectangle.Height - 1));
                graphics.DrawLine(Pens.Black, new Point(0, clientRectangle.Height - 1), new Point(clientRectangle.Width - 1, clientRectangle.Height - 1));
                graphics.DrawLine(Pens.Black, new Point(clientRectangle.Width - 1, clientRectangle.Height - 1), new Point(clientRectangle.Width - 1, 20));

                using (Brush brush = new SolidBrush(this.ForeColor))
                {
                    using (StringFormat format = new StringFormat())
                    {
                        format.HotkeyPrefix = this.ShowKeyboardCues ? HotkeyPrefix.Show : HotkeyPrefix.Hide;
                        if (this.RightToLeft == RightToLeft.Yes)
                        {
                            format.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
                        }
                        Rectangle titleRect = new Rectangle(0, -20, clientRectangle.Width, 20);
                        if (base.Enabled)
                        {
                            DrawingUtilities.DrawString(graphics, this.Text, this.Font, Brushes.White, titleRect, format);
                        }
                        else
                        {
                            DrawingUtilities.DrawStringDisabled(graphics, this.Text, this.Font, _disabledColor, titleRect, format);
                        }
                    }
                }
            }
            finally
            {
                pen.Dispose();
                pen2.Dispose();
            }
        }

        protected override void OnFontChanged(EventArgs e)
        {
            this._titleHeight = -1;
            base.Invalidate();
            base.OnFontChanged(e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            this.DrawTitleBox(e);
            base.OnPaint(e);
        }

        protected override void OnResize(EventArgs eventargs)
        {
            Invalidate(true);
            btnClose.Location = new System.Drawing.Point(this.Size.Width - btnClose.Size.Width - 4, 2);
            base.OnResize(eventargs);
        }

        public override string ToString()
        {
            return (base.ToString() + ", Text: " + this.Text);
        }

        private void WmEraseBkgnd(ref Message m)
        {
            Rectangle rect = this.ClientRectangle;
            using (Graphics graphics = Graphics.FromHdcInternal(m.WParam))
            {
                using (Brush brush = new SolidBrush(this.BackColor))
                {
                    graphics.FillRectangle(brush, rect.Left - 1, rect.Top - 1, rect.Right - rect.Left, rect.Bottom - rect.Top);
                }
            }
            m.Result = (IntPtr)1;
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override void WndProc(ref Message m)
        {
            int msg = m.Msg;
            if (msg != 20)
            {
                switch (msg)
                {
                    case (int)Win32.WM_MESSAGE.WM_NCCALCSIZE:
                        {
                            if (m.WParam == IntPtr.Zero)
                            {
                                Win32.NCCALCSIZE_PARAMS csp;

                                csp = (Win32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(Win32.NCCALCSIZE_PARAMS));
                                csp.rgrc0.Top += 0;
                                //csp.rgrc0.Left += 1;
                                //csp.rgrc0.Right += 1;
                                //csp.rgrc0.Bottom += 1;
                                Marshal.StructureToPtr(csp, m.LParam, false);
                            }
                            break;
                        }
                    case 0x3d:
                        {
                            base.WndProc(ref m);
                            if (((int)((long)m.LParam)) == -12)
                            {
                                m.Result = IntPtr.Zero;
                            }
                            return;
                        }
                    case (int)Win32.WM_MESSAGE.WM_NCHITTEST:
                        {
                            Point pt = PointToClient(new Point(m.LParam.ToInt32()));

                            //if (!_rcButton.IsEmpty && _rcButton.Contains(pt))
                            {
                                //System.Diagnostics.Debug.WriteLine("On Button");
                                m.Result = (IntPtr)18;//HTBORDER
                                return;
                            }

                            //break;
                        }
                }
                if (msg != 0x318)
                {
                    base.WndProc(ref m);
                    return;
                }
            }
            this.WmEraseBkgnd(ref m);
        }

        public override Rectangle DisplayRectangle
        {
            get
            {
                Size clientSize = base.ClientSize;
                //if (this._fontHeight == -1)
                //{
                //    this._fontHeight = this.Font.Height;
                //}
                Padding padding = base.Padding;
                //return new Rectangle(padding.Left, _titleHeight, Math.Max(clientSize.Width - padding.Horizontal, 0), Math.Max((clientSize.Height - _titleHeight) - padding.Vertical, 0));
                return new Rectangle(padding.Left + 1, _titleHeight, Math.Max(clientSize.Width - padding.Horizontal, 0) - 2, Math.Max((clientSize.Height - _titleHeight) - padding.Vertical, 0) - 1);
            }
        }

        [Localizable(true), Browsable(true)]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {

                base.Text = value;
                base.Invalidate(true);
            }
        }

        // Nested Types
        [ComVisible(true)]
        internal class TitlePanelAccessibleObject : Control.ControlAccessibleObject
        {
            // Methods
            internal TitlePanelAccessibleObject(TitlePanel owner)
                : base(owner)
            {
            }

            // Properties
            public override AccessibleRole Role
            {
                get
                {
                    AccessibleRole accessibleRole = base.Owner.AccessibleRole;
                    if (accessibleRole != AccessibleRole.Default)
                    {
                        return accessibleRole;
                    }
                    return AccessibleRole.Grouping;
                }
            }
        }
    }
}
